package life.sweet.community.service;

import life.sweet.community.dto.NotificationDTO;
import life.sweet.community.dto.PaginationDTO;
import life.sweet.community.enums.NotificationStstusEnum;
import life.sweet.community.enums.NotificationTypeEnum;
import life.sweet.community.exception.CustomErrorCode;
import life.sweet.community.exception.CustomException;
import life.sweet.community.mapper.NotificationMapper;
import life.sweet.community.mapper.UserMapper;
import life.sweet.community.model.*;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
public class NotificationService {
    @Autowired
    private NotificationMapper notificationMapper;

    public PaginationDTO list(Long userId, Integer page, Integer size) {
        PaginationDTO<NotificationDTO> paginationDTO = new PaginationDTO();
        NotificationExample notificationExample = new NotificationExample();
        notificationExample.createCriteria().andReceiverEqualTo(userId);
        Integer totalCount = (int)notificationMapper.countByExample(notificationExample);
        if(totalCount == 0) {
            return new PaginationDTO();
        }
        Integer totalPage;

        if(totalCount % size == 0) {
            totalPage =  totalCount / size;
        } else {
            totalPage = totalCount / size + 1;
        }

        if(page < 1) {
            page = 1;
        }

        if(page > totalPage) {
            page = totalPage;
        }

        paginationDTO.setPagination(totalPage,page,size);
        Integer offset = size * (page -1);
        NotificationExample notificationExampleWithPage = new NotificationExample();
        notificationExampleWithPage.setOrderByClause("gmt_create desc");
        notificationExampleWithPage.createCriteria().andReceiverEqualTo(userId);
        RowBounds rowBound = new RowBounds(offset,size);
        List<Notification> notifications = notificationMapper.selectByExampleWithRowbounds(notificationExampleWithPage,rowBound);
        if(CollectionUtils.isEmpty(notifications)) {
            return paginationDTO;
        }

        /* Set<Long> distinctUserIds = notifications.stream().map(notification -> notification.getNotifier()).collect(Collectors.toSet());
        List<Long> dbUserids = new ArrayList<>(distinctUserIds);
        UserExample userExample = new UserExample();
        userExample.createCriteria().andIdIn(dbUserids);
        List<User> users = userMapper.selectByExample(userExample);
        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(u -> u.getId(), u -> u));
        List<NotificationDTO> dtoList = new ArrayList<>(); */
        List<NotificationDTO> list = new ArrayList<>();
        for (Notification no : notifications ) {
            NotificationDTO dto = new NotificationDTO();
            BeanUtils.copyProperties(no, dto);
            dto.setTypeName(NotificationTypeEnum.nameOfType(no.getType()));
            list.add(dto);
        }
        paginationDTO.setData(list);
        return paginationDTO;
    }

    /**
     * 未读的通知数
     * @param id
     * @return
     */
    public int countUnreadNotifications(Long id) {
        NotificationExample example = new NotificationExample();
        example.createCriteria().andReceiverEqualTo(id).andStatusEqualTo(NotificationStstusEnum.UNREAD.getStatus());
        example.setOrderByClause("gmt_create desc");
        int count = (int) notificationMapper.countByExample(example);
        return count;
    }

    public NotificationDTO read(Long id, User user) {
        Notification notification = notificationMapper.selectByPrimaryKey(id);
        if(notification == null) {
            throw new CustomException(CustomErrorCode.NOTIFICATION_NOT_FOUND);
        }
        if(!Objects.equals(notification.getReceiver(),user.getId())) {
            throw new CustomException(CustomErrorCode.READ_NOTIFICATION_FAIL);
        }
        notification.setStatus(NotificationStstusEnum.READ.getStatus());
        notificationMapper.updateByPrimaryKey(notification);

        NotificationDTO dto = new NotificationDTO();
        BeanUtils.copyProperties(notification,dto);
        dto.setTypeName(NotificationTypeEnum.nameOfType(notification.getType()));
        return dto;
    }
}
